﻿using Grpc.Core;
using MX.Core.Extensions;
using System;
using System.Threading.Tasks;
using UserCenter.Api.Core;
using UserCenter.Api.Tools;
using UserCenter.BLL;
using UserCenter.Grpc;
using UserCenter.Models;
using UserCenter.Api.Models;
using Newtonsoft.Json.Linq;
using MX.Core.Log;
using Newtonsoft.Json;
using System.Collections.Generic;
using SdkPwdAuthRequest = UserCenter.Grpc.Sdk.PwdAuthRequest;
using ClientPwdAuthRequest = UserCenter.Grpc.Client.PwdAuthRequest;
using SdkSetExtRequest = UserCenter.Grpc.Sdk.SetExtRequest;
using ClientSetExtRequest = UserCenter.Grpc.Client.SetExtRequest;
using SdkSetParentRequest = UserCenter.Grpc.Sdk.SetParentRequest;
using ClientSetParentRequest = UserCenter.Grpc.Client.SetParentRequest;
using SdkSetPasswordRequest = UserCenter.Grpc.Sdk.SetPasswordRequest;
using ClientSetPasswordRequest = UserCenter.Grpc.Client.SetPasswordRequest;
using System.Linq;

namespace UserCenter.Api.Services
{
    public class BaseMerchantImpl
    {
        ILogger logger = Logger.GetLogger(nameof(BaseMerchantImpl));
        const int ECH = 0x7;


        /// <summary>
        /// 密码注册
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<RegisterResponse> PwdRegister(PwdRegisterRequest request, ServerCallContext context)
        {

            if (string.IsNullOrEmpty(request.UserName))
            {
                context.Throw(ECH, 0x2);
                return null;
            }
            bool exists = MemberBLL.CheckUserName(request.UserName);
            if (exists)
            {
                context.Throw(ECH, 16);
                return null;
            }
            var memberId = MemberBLL.Create(context.MerchantId(), request.UserName, ApiConfig.Default.DefaultAvaterUrl);
            if (memberId < 1)
            {
                context.Throw(ECH, 05);
                return null;
            }
            else
            {
                return Task.FromResult(new RegisterResponse()
                {
                    MemberId = memberId
                });
            }
        }

        /// <summary>
        /// 密码验证
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>

        public Task<AuthResponse> PwdAuth(ClientPwdAuthRequest request, ServerCallContext context)
        {
            return PwdAuth(new AuthRequest
            {
                DeviceId = request.DeviceId,
                DeviceName = request.DeviceName,
                DeviceType = request.DeviceType,
                Password = request.Password,
                Type = request.Type,
                Ip = context.ClientIp(),
                UserName = request.UserName
            }, context);
        }


        /// <summary>
        /// 密码验证
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<AuthResponse> PwdAuth(SdkPwdAuthRequest request, ServerCallContext context)
        {
            return PwdAuth(new AuthRequest
            {
                DeviceId = request.DeviceId,
                DeviceName = request.DeviceName,
                DeviceType = request.DeviceType,
                Password = request.Password,
                Type = request.Type,
                Ip = request.Ip,
                UserName = request.UserName
            }, context);
        }

        /// <summary>
        /// 密码验证
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        private Task<AuthResponse> PwdAuth(AuthRequest request, ServerCallContext context)
        {

            var deviceType = AuthUtils.ToDeviceType(request.DeviceType);
            if (!deviceType.HasValue)
            {
                context.Throw(ECH, 10);
                return null;
            }
            if (request.Type > byte.MaxValue || request.Type < byte.MinValue)
            {
                context.Throw(ECH, 0x9);
                return null;
            }

            var member = MemberBLL.Info(context.MerchantId(), request.UserName);
            if (member != null)
            {
                var password = MemberBLL.Password(member.MemberId, Convert.ToByte(request.Type));

                if (password != null)
                {
                    if (password.Password.Equals(request.Password, StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (member.LoginStatus == Member.Status.Enable)
                        {
                            string token = Guid.NewGuid().ToString("N");
                            if (MemberBLL.Auth(member.MemberId, token, request.Ip, request.DeviceId, request.DeviceName, deviceType.Value, AuthSource.Client))
                            {
                                return Task.FromResult(new AuthResponse
                                {
                                    Status = AuthStatus.Success,
                                    Expire = DateTime.Now.AddDays(7).ToTimestamp(),
                                    MemberId = member.MemberId,
                                    Token = token
                                });
                            }
                            else
                            {
                                return Task.FromResult(new AuthResponse
                                {
                                    Status = AuthStatus.Faild
                                });
                            }
                        }
                        else
                        {
                            return Task.FromResult(new AuthResponse
                            {
                                Status = AuthStatus.MemberStatusErr
                            });
                        }

                    }
                    else
                    {
                        return Task.FromResult(new AuthResponse
                        {
                            Status = AuthStatus.PasswordErr
                        });
                    }
                }
                else
                {
                    return Task.FromResult(new AuthResponse
                    {
                        Status = AuthStatus.NotFound
                    });

                }
            }
            else
            {
                return Task.FromResult(new AuthResponse
                {
                    Status = AuthStatus.NotFound
                });
            }
        }


        /// <summary>
        /// 设置扩展数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<BoolValue> SetExt(SdkSetExtRequest request, ServerCallContext context)
        {
            if (!MemberBLL.CheckMember(context.MerchantId(), request.MemberId))
            {
                context.Throw(ECH, 0x8);
                return null;
            }
            return SetExt(new SetExtRequest
            {
                JsonData = request.JsonData,
                MemberId = request.MemberId
            }, context);
        }

        /// <summary>
        /// 设置扩展数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<BoolValue> SetExt(ClientSetExtRequest request, ServerCallContext context)
        {
            return SetExt(new SetExtRequest
            {
                JsonData = request.JsonData,
                MemberId = context.MemberId()
            }, context);
        }


        /// <summary>
        /// 设置扩展数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        private Task<BoolValue> SetExt(SetExtRequest request, ServerCallContext context)
        {

            JObject source = null;
            try
            {
                source = JObject.Parse(request.JsonData);
            }
            catch (Exception ex)
            {
                logger.Error(ex, "");
            }
            if (source == null)
            {
                context.Throw(ECH, 0x6);
                return null;
            }
            if (request.MemberId < 1)
            {
                context.Throw(ECH, 0x7);
                return null;
            }
            var distStr = MemberBLL.Ext(request.MemberId);
            bool exists = !string.IsNullOrEmpty(distStr);
            if (exists)
            {
                var dist = JObject.Parse(distStr);
                dist.Merge(source);
                source = dist;
            }
            bool saved = MemberBLL.SetExt(request.MemberId, source.ToString(Formatting.None), exists);
            return Task.FromResult(new BoolValue() { Value = saved });
        }


        /// <summary>
        /// 设置父级
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<BoolValue> SetParent(SdkSetParentRequest request, ServerCallContext context)
        {
            if (!MemberBLL.CheckMember(context.MerchantId(), request.ParentId))
            {
                context.Throw(ECH, 0x8);
                return null;
            }
            return SetParent(new SetParentsRequest
            {

                MemberId = request.MemberId,
                ParentId = request.ParentId
            }, context);
        }

        /// <summary>
        /// 设置父级
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<BoolValue> SetParent(ClientSetParentRequest request, ServerCallContext context)
        {
            return SetParent(new SetParentsRequest
            {

                MemberId = context.MemberId(),
                ParentId = request.ParentId

            }, context);
        }


        /// <summary>
        /// 设置父级
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<BoolValue> SetParent(SetParentsRequest request, ServerCallContext context)
        {
            if (request.ParentId == request.MemberId)
            {
                context.Throw(ECH, 23);
                return null;
            }

            if (MemberBLL.GetParentId(request.ParentId) == request.MemberId)
            {
                //不能互为父级
                context.Throw(ECH, 24);
                return null;
            }
            if (MemberBLL.GetChildCount(request.MemberId) > 0)
            {
                //不能互为父级
                context.Throw(ECH, 25);
                return null;
            }
            bool saved = MemberBLL.SetParent(request.MemberId, request.ParentId, ApiConfig.Default.CountLayer);
            return Task.FromResult(new BoolValue() { Value = saved });
        }


        /// <summary>
        /// 设置密码
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<BoolValue> SetPassword(SdkSetPasswordRequest request, ServerCallContext context)
        {
            return SetPassword(new SetPasswordRequest()
            {
                MemberId = request.MemberId,
                Password = request.Password,
                Type = request.Type
            }, context);
        }


        /// <summary>
        /// 设置密码
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        private Task<BoolValue> SetPassword(SetPasswordRequest request, ServerCallContext context)
        {
            if (!MemberBLL.CheckMember(context.MerchantId(), request.MemberId))
            {
                context.Throw(ECH, 0x8);
                return null;
            }
            if (request.Type >= byte.MinValue && request.Type <= byte.MaxValue)
            {
                var type = Convert.ToByte(request.Type);
                bool saved = false;
                var password = MemberBLL.Password(request.MemberId, type);
                if (password != null)
                {
                    if (!password.Password.Equals(request.Password))
                    {
                        saved = MemberBLL.UpdatePassword(request.MemberId, type, request.Password);
                    }
                    else
                    {
                        saved = true;
                    }
                }
                else
                {
                    saved = MemberBLL.CreatePassword(request.MemberId, type, request.Password);
                }
                return Task.FromResult(new BoolValue() { Value = saved });
            }
            else
            {
                context.Throw(ECH, 0x9);
                return null;
            }



        }

        /// <summary>
        /// 检查凭据
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<CheckTokenResponse> CheckToken(CheckTokenRequest request, ServerCallContext context)
        {
            MemberAuthToken token = MemberBLL.Token(request.Token);
            if (token != null)
            {
                return Task.FromResult(new CheckTokenResponse()
                {
                    MemberId = token.MemberId,
                    Success = true
                });
            }
            else
            {
                return Task.FromResult(new CheckTokenResponse()
                {
                    Success = false
                });
            }
        }

        /// <summary>
        /// 获取一个会员
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<GetMemberResponse> GetMember(GetMemberRequest request, ServerCallContext context)
        {
            if (!MemberBLL.CheckMember(context.MerchantId(), request.MemberId))
            {
                context.Throw(ECH, 0x8);
                return null;
            }
            return GetMember(request.MemberId, context);
        }



        /// <summary>
        /// 获取一个会员
        /// </summary>
        /// <param name="memberId"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task<GetMemberResponse> GetMember(long memberId, ServerCallContext context)
        {
            var member = MemberBLL.Info(memberId);
            return GetMember(member, context);
        }


        public Task<GetMemberResponse> GetMember(Member member, ServerCallContext context)
        {
            var extJson = MemberBLL.Ext(member.MemberId) ?? "";
            return Task.FromResult(new GetMemberResponse()
            {
                AvatarUrl = member.AvatarUrl,
                ExtJson = extJson,
                LoginStatus = member.LoginStatus.ToGrpcLoginStatus(),
                MemberId = member.MemberId,
                UserName = member.UserName
            });
        }
    }
}
